package com.crux.ribbon;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;

import java.lang.reflect.Constructor;

//@Configuration
@Slf4j
public class CustomLoadBalancerConfiguration {

    @Bean
    @Order(Integer.MIN_VALUE)
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context,
            @Value("${crux.load-balance.class:com.crux.ribbon.ApiVersionServiceInstanceListSupplier}")
                    String serviceInstanceListSupplierClassName) {
        ServiceInstanceListSupplier serviceInstanceListSupplier = ServiceInstanceListSupplier.builder()
                .withBlockingDiscoveryClient()
                .withZonePreference()
                .withCaching()
                .build(context);
        try {
            log.info("使用负载均衡算法类:{}", serviceInstanceListSupplierClassName);
            Class<ServiceInstanceListSupplier> clazz = (Class<ServiceInstanceListSupplier>) Class.forName(serviceInstanceListSupplierClassName);
            Constructor<ServiceInstanceListSupplier> constructor = clazz.getDeclaredConstructor(ServiceInstanceListSupplier.class);
            ServiceInstanceListSupplier serviceInstanceListSupplierInstance = constructor.newInstance(serviceInstanceListSupplier);
            //return new ApiVersionServiceInstanceListSupplier(serviceInstanceListSupplier);
            return serviceInstanceListSupplierInstance;
        } catch (Exception e) {
            throw new BeanCreationException(String.format("负载均衡类%s实例化失败", serviceInstanceListSupplierClassName));
        }
    }


    @Bean
    ReactorLoadBalancer<ServiceInstance> eurekaLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory,
                                                            ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier) {
        String serviceId = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new EurekaLoadBalancer(serviceId, discoveryClientServiceInstanceListSupplier);
    }
}
